// ///////////////////////////// MIT License //////////////////////////////////// //
//                                                                                //
// Copyright (c) 2010 David Zsolt Manrique                                        //
//                    david.zsolt.manrique@gmail.com                              //
//                                                                                //
// Permission is hereby granted, free of charge, to any person obtaining a copy   //
// of this software and associated documentation files (the "Software"), to deal  //
// in the Software without restriction, including without limitation the rights   //
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      //
// copies of the Software, and to permit persons to whom the Software is          //
// furnished to do so, subject to the following conditions:                       //
//                                                                                //
// The above copyright notice and this permission notice shall be included in     //
// all copies or substantial portions of the Software.                            //
//                                                                                //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    //
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  //
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN      //
// THE SOFTWARE.                                                                  //
//                                                                                //
// ////////////////////////////////////////////////////////////////////////////// //


#include "potential.h"


std::string potential_base::record_atom_index() const {   throw;  }
std::string potential_base::record_key() const {  throw;  }
std::string potential_base::record_params() const { throw;   }
bool potential_base::equivalent(const potential_base & r) const {return false;}
void potential_base::eval(real_type & u,vector_array_type & f,const vector_array_type & r) const {throw;}
void potential_base::eval(real_type & u,vector_array_type & f,const vector_array_type & r,const real_type & t) const {throw;}
void potential_base::peval(real_type & u,vectorx_type & dp,const vectorx_type &  p,const vector_array_type & r) {throw;}

//! \Todo It has to be removed since it is not used!
void fit_base::pdiff(real_type & u,vectorx_type & dp,const vectorx_type & p,const vector_array_type & r) {throw;} 


background::constant::constant(param_type p_u0) : p_u0(p_u0) {}
bool background::constant::equivalent(const potential_base & r) const 
{ 
	if(typeid(r) == typeid(*this)) return true;
	return false;
}
background::constant_fit::constant_fit(param_type p_u0, vector_index_type i_u0) : i_u0(i_u0), background::constant(p_u0) {}


bond::potential::potential(
				array_index_type i_,array_index_type j_
				) : 
				i(i_),j(j_)
{ function::sort(i,j); }

bool bond::potential::equivalent(const potential_base & r) const 
{ 
	if(typeid(r) == typeid(*this))
	{ 
		const potential & p = reinterpret_cast<const potential&>(r); //! this may be unsafe!!, ez meg okozhat gondot!
		return ( (i == p.i) && (j == p.j) );
	}
	return false;
}

bond::harm::harm(
				param_type p_k,param_type p_r0,
				array_index_type i,array_index_type j
				) : 
				p_k(p_k),p_r0(p_r0),
				potential(i,j) 
{}
			

bond::harm_fit::harm_fit(
				param_type p_k,  vector_index_type i_k,
				param_type p_r0, vector_index_type i_r0,
				array_index_type i,array_index_type j
				) : 
				i_k(i_k),i_r0(i_r0),
				bond::harm(p_k,p_r0,i,j) 
{}


bond::mors::mors(
				param_type p_E0,param_type p_k,param_type p_r0,
				array_index_type i,array_index_type j
				) : 
				p_E0(p_E0),p_k(p_k),p_r0(p_r0),
				potential(i,j) 
{}
			

bond::mors_fit::mors_fit(param_type p_E0,  vector_index_type i_E0,
				param_type p_k,  vector_index_type i_k,
				param_type p_r0, vector_index_type i_r0,
				array_index_type i,array_index_type j
				) : 
				i_E0(i_E0),i_k(i_k),i_r0(i_r0),
				bond::mors(p_E0,p_k,p_r0,i,j) 
{}





//!
angle::potential::potential(
				array_index_type i_,array_index_type j_,array_index_type k_
				) : 
				i(i_),j(j_),k(k_)
{ function::sort(i,k); }

bool angle::potential::equivalent(const potential_base & r) const 
{ 
	if(typeid(r) == typeid(*this))
	{ 
		const potential & p = reinterpret_cast<const potential&>(r); //! this may be unsafe!!, ez meg okozhat gondot!
		return ( (i == p.i) && (j == p.j) && (k == p.k) );
	}
	return false;
}

//!
angle::harm::harm(
				param_type p_k,param_type p_phi0,
				array_index_type i,array_index_type j,array_index_type k
				) : 
				p_k(p_k),p_phi0(p_phi0),
				potential(i,j,k) 
{}



angle::harm_fit::harm_fit(
				param_type p_k,  vector_index_type i_k,
				param_type p_phi0, vector_index_type i_phi0,
				array_index_type i,array_index_type j,array_index_type k
				) : 
				i_k(i_k),i_phi0(i_phi0),
				angle::harm(p_k,p_phi0,i,j,k) 
{}

//!
angle::hcos::hcos(
				param_type p_k,param_type p_cosphi0,
				array_index_type i,array_index_type j,array_index_type k
				) : 
				p_k(p_k),p_cosphi0(p_cosphi0),
				potential(i,j,k) 
{}



angle::hcos_fit::hcos_fit(
				param_type p_k,  vector_index_type i_k,
				param_type p_cosphi0, vector_index_type i_cosphi0,
				array_index_type i,array_index_type j,array_index_type k
				) : 
				i_k(i_k),i_cosphi0(i_cosphi0),
				angle::hcos(p_k,p_cosphi0,i,j,k) 
{}










//!
//!
dihedral::potential::potential(
				array_index_type i_,array_index_type j_,array_index_type k_,array_index_type l_
				) : 
				i(i_),j(j_),k(k_),l(l_)
{ if(i > j) { std::swap(i,l); std::swap(j,k); } }

bool dihedral::potential::equivalent(const potential_base & r) const 
{ 
	if(typeid(r) == typeid(*this))
	{ 
		const potential & p = reinterpret_cast<const potential&>(r); //! this may be unsafe!!, ez meg okozhat gondot!
		return ( (i == p.i) && (j == p.j) && (k == p.k) && (l == p.l) );
	}
	return false;
}

//!
dihedral::harm::harm(
				param_type p_k,param_type p_phi0,
				array_index_type i,array_index_type j,array_index_type k,array_index_type l
				) : 
				p_k(p_k),p_phi0(p_phi0),
				potential(i,j,k,l) 
{}



dihedral::harm_fit::harm_fit(
				param_type p_k,  vector_index_type i_k,
				param_type p_phi0, vector_index_type i_phi0,
				array_index_type i,array_index_type j,array_index_type k,array_index_type l
				) : 
				i_k(i_k),i_phi0(i_phi0),
				dihedral::harm(p_k,p_phi0,i,j,k,l) 
{}

				/*
//!
dihedral::hcos::hcos(
				param_type p_k,param_type p_cosphi0,
				array_index_type i,array_index_type j,array_index_type k,array_index_type l
				) : 
				p_k(p_k),p_cosphi0(p_cosphi0),
				potential(i,j,k,l) 
{}



dihedral::hcos_fit::hcos_fit(
				param_type p_k,  vector_index_type i_k,
				param_type p_cosphi0, vector_index_type i_cosphi0,
				array_index_type i,array_index_type j,array_index_type k,array_index_type l
				) : 
				i_k(i_k),i_cosphi0(i_cosphi0),
				dihedral::hcos(p_k,p_cosphi0,i,j,k,l) 
{}*/

//!
dihedral::cosf::cosf(
				param_type p_A,param_type p_d,param_type p_m,
				array_index_type i,array_index_type j,array_index_type k,array_index_type l
				) : 
				p_A(p_A),p_d(p_d),p_m(p_m),
				potential(i,j,k,l) 
{}



dihedral::cosf_fit::cosf_fit(
				param_type p_A,  vector_index_type i_A,
				param_type p_d, vector_index_type i_d,
				param_type p_m, vector_index_type i_m,
				array_index_type i,array_index_type j,array_index_type k,array_index_type l
				) : 
				i_A(i_A),i_d(i_d),i_m(i_m),
				dihedral::cosf(p_A,p_d,p_m,i,j,k,l) 
{}
















inversion::potential::potential(
				array_index_type i_,array_index_type j_,array_index_type k_,array_index_type l_
				) : 
				i(i_),j(j_),k(k_),l(l_)
{ function::sort(j,k,l); }

bool inversion::potential::equivalent(const potential_base & r) const 
{ 
	if(typeid(r) == typeid(*this))
	{ 
		const potential & p = reinterpret_cast<const potential&>(r); //! this may be unsafe!!, ez meg okozhat gondot!
		return ( (i == p.i) && (j == p.j) && (k == p.k) && (l == p.l) );
	}
	return false;
}



//!
inversion::plan::plan(
				param_type p_A,
				array_index_type i,array_index_type j,array_index_type k,array_index_type l
				) : 
				p_A(p_A),
				potential(i,j,k,l) 
{}



inversion::plan_fit::plan_fit(
				param_type p_A,  vector_index_type i_A,
				array_index_type i,array_index_type j,array_index_type k,array_index_type l
				) : 
				i_A(i_A),
				inversion::plan(p_A,i,j,k,l) 
{}

